# 字符串是不可变的
"""
模块说明
----------
本模块演示了 Python 字符串（str）的创建、访问、切片、常用操作及进阶用法，覆盖从基础索引到格式化、编码、对齐、Unicode 处理与正则替换等内容。
所有示例均基于不可变的字符串对象，并展示常见方法的用法与返回值特性。
主要内容概览
-------------
- 字符串创建
    - 单引号、双引号、三引号（多行）、原始字符串（r/R 前缀）等声明方式。
- 不可变性
    - 字符串是不可变类型，不能通过索引直接修改单个字符（应使用拼接或替换产生新字符串）。
访问与切片
-------------
- 索引访问：支持正向（0 起）与负向索引（-1 为最后一个字符）。
- 切片：支持 start:stop:step 形式的任意切片与步长，包括反向切片（step 为负值）用于反转字符串或取逆序片段。
- 常见用法示例：取前缀、后缀、间隔取字符、反转字符串等。
拼接、重复与成员判断
-------------------
- 拼接：使用 + 或 join 进行字符串连接。
- 重复：使用 * 运算符重复字符串。
- 成员判断：使用 in / not in 判断子串或字符是否存在。
遍历
----
- 逐字符遍历：for char in s。
- 使用 enumerate 获取索引和值：for index, char in enumerate(s)。
常用字符串方法
----------------
- 去除空白：strip(), lstrip(), rstrip()。
- 大小写转换：lower(), upper(), title(), swapcase()（示例中展示了 lower/upper）。
- 查找替换：find() 返回首个匹配索引或 -1；count() 计数；replace() 替换产生新字符串。
- 切分与连接：split(sep) 将字符串分割为列表；str.join(iterable) 将可迭代对象连接为新字符串。
- 前缀/后缀判断：startswith(), endswith()。
- 字符类别判断：isdigit(), isalpha(), isalnum() 等。
- 对齐：ljust(width, fillchar), rjust(width, fillchar), center(width, fillchar)。
格式化
------
- 旧式格式化：%s, %d 等占位符。
- str.format()：位置或关键字替换，支持格式说明符。
- f-string（字面插值）：内联表达式与格式说明符（例如保留小数、对齐、千分位等）。
- 多行格式化：使用三引号或 \n 转义实现多行文本。
编码与解码
-----------
- 使用 bytes = str.encode(encoding) 将字符串编码为字节串；使用 str = bytes.decode(encoding) 解码回字符串。
- 示例展示了 UTF-8 与 GBK 编码/解码互转（注意实际平台兼容性与错误处理）。
长度与比较
------------
- 长度：len(s) 返回字符数量（注意对 Unicode 的行为以 Python 抽象字符为准）。
- 比较：支持 ==, !=, <, >, <=, >= 基于字典序比较。
转义与特殊字符
----------------
- 常见转义序列：\n（换行）、\t（制表符）、\\（反斜杠）、\" 与 \'。
- 原始字符串 r"..." 会保留反斜杠字面值，适合正则或包含大量转义字符的场景。
数字与字段格式化
-----------------
- f-string 或 format 支持数值格式，如固定小数点 {:.2f}、科学计数法 {:.2e}、百分比 {:.2%}、千分位{:,}、以及将整数以十六进制或二进制展示（:x, :b）。
Unicode 与码点
----------------
- 字符串可包含 Unicode 字符（例如中文），可以使用 ord() 获取字符的 Unicode 码点。
- 遍历 Unicode 字符串时按字符迭代（组合字符与复合字符需注意）。
多行字符串与续行
-----------------
- 三引号用于多行字符串文本（便于文档或长文本）。
- 使用反斜杠续行将长字符串在代码中分行表示但生成单行字符串。
反转与排序
-----------
- 反转：可使用切片 s[::-1] 或 ''.join(reversed(s))。
- 排序：sorted(s) 返回字符排序列表，可通过 ''.join(sorted(s)) 生成排序后的字符串。
正则查找与替换
----------------
- 使用 re.findall() 查找符合模式的所有子串（示例中查找以 "ain" 结尾的单词）。
- 使用 re.sub() 按正则表达式替换匹配项（示例中将匹配词替换为占位符）。
模板替换
--------
- string.Template 提供基于 $name 的简单模板替换，用于某些模板化文本场景。
注意事项与性能提示
-------------------
- 由于不可变性，频繁拼接大量字符串时建议使用列表收集后用 ''.join() 合并，或使用 io.StringIO/bytearray 等缓冲方案以提升性能。
- 编码/解码需显式指定编码并处理异常（如非目标编码字符），避免隐式采用系统默认编码导致的平台相关问题。
- 正则模块处理复杂文本时注意转义与边界（例如 \b 单词边界）以获得预期结果。
本模块为教学示例，旨在帮助理解与熟练掌握 Python 中字符串的常见用法与细节。
"""

# 创建字符串
str1 = "hello world"
str1 = 'hello world'
str1 = """hello world"""
str1 = '''hello world'''    
# 访问字符串
print(str1[0])  # h
print(str1[-1])  # d
# 切片操作
print(str1[0:5])  # hello
print(str1[:5])  # hello
print(str1[6:])  # world
print(str1[::2])  # hlo ol
print(str1[::-1])  # dlrow olleh

# 字符串的相加
str1 = "hello"
str2 = "world"
print(str1) # hello
# str1[1] = 'a'  # 报错 字符串不支持修改
str1 + str2  # helloworld

# 字符串的乘法
print(str1 * 3)  # hellohellohello
print('-' * 10)  # ----------

# 判断某个元素是否在字符串中
print('h' in str1)  # True
print('a' not in str1)  # True
print("ell" in str1)  # True

# 原始字符串
str1 = "hello \t \t world"
print(str1)  # hello          world
str1 = r"hello \t \t world"
print(str1)  # hello \t \t world
str1 = R"hello \t \t world"
print(str1)  # hello \t \t world

# 字符串的遍历
for char in str1:
    print(char)     

for index, char in enumerate(str1):
    print("索引为:", index, "对应的字符为:", char)

# 字符串的常用方法
str1 = "  hello world  "
print(str1.strip())  # 去除两端空格 hello world
print(str1.lstrip())  # 去除左侧空格 hello world
print(str1.rstrip())  # 去除右侧空格   hello world
str2 = "HELLO WORLD"
print(str2.lower())  # hello world
str3 = "hello world"
print(str3.upper())  # HELLO WORLD
str4 = "hello world"
print(str4.replace("world", "python"))  # hello python
str5 = "hello world"
print(str5.split(" "))  # ['hello', 'world']
str6 = "hello"
print(str6.join(["hello", "world"]))  # hellohelloworld
str7 = "hello world"
print(str7.find("world"))  # 6
print(str7.count("l"))  # 3     
str8 = "hello world"
print(str8.startswith("hello"))  # True
print(str8.endswith("world"))  # True
str9 = "123"
print(str9.isdigit())  # True
str10 = "abc"
print(str10.isalpha())  # True
str11 = "abc123"
print(str11.isalnum())  # True

# 格式化字符串
name = "Alice"
age = 30
# 旧式格式化
print("My name is %s, I am %d years old." % (name, age))
# 新式格式化
print("My name is {}, I am {} years old.".format(name, age))
# f字符串格式化
print(f"My name is {name}, I am {age} years old.")
# 多行字符串格式化
print(f"""My name is {name},
I am {age} years old.""")
# 字符串的编码和解码
str1 = "hello world"
bytes1 = str1.encode("utf-8")  # 编码
print(bytes1)  # b'hello world'
str2 = bytes1.decode("utf-8")  # 解码
print(str2)  # hello world
# 字符串的长度
print(len(str1))  # 11
# 字符串的比较
strA = "apple"
strB = "banana"
print(strA == strB)  # False
print(strA != strB)  # True
print(strA < strB)  # True
print(strA > strB)  # False
print(strA <= strB)  # True
print(strA >= strB)  # False
# 字符串的转义字符
str1 = "hello\nworld"
print(str1)
str2 = "hello\tworld"
print(str2)
str3 = "hello\\world"
print(str3)
str4 = "He said, \"Hello World!\""
print(str4)
str5 = 'It\'s a beautiful day.'
print(str5)
# 字符串的格式化方法
name = "Bob"
score = 95.5
print("Student Name: {}, Score: {:.2f}".format(name, score))
print(f"Student Name: {name}, Score: {score:.2f}")
# 多行字符串
str1 = """This is a multi-line string.
It can span multiple lines.
Useful for documentation or long text."""
print(str1)     
# 转义多行字符串
str2 = "This is a multi-line string.\nIt can span multiple lines.\nUseful for documentation or long text."
print(str2)
# 字符串的反转
str1 = "hello"
reversed_str1 = str1[::-1]
print(reversed_str1)  # olleh
# 字符串的拼接
str_list = ["hello", "world", "from", "python"]
joined_str = " ".join(str_list)
print(joined_str)  # hello world from python
# 字符串的切片步长
str1 = "abcdefghij"
print(str1[::2])  # acegi
print(str1[1::2])  # bdfhj  
print(str1[::-2])  # jhfdb
print(str1[5:1:-1])  # fedc
# 字符串的查找和替换
str1 = "the quick brown fox jumps over the lazy dog"
index = str1.find("fox")
print(index)  # 16
count = str1.count("the")
print(count)  # 2
new_str1 = str1.replace("fox", "cat")
print(new_str1)  # the quick brown cat jumps over the lazy dog
# 字符串的对齐
str1 = "hello"
print(str1.ljust(10, '-'))  # hello-----
print(str1.rjust(10, '-'))  # -----hello
print(str1.center(10, '-'))  # --hello---

# 字符串的编码格式
str1 = "hello world"
bytes_utf8 = str1.encode("utf-8")   
print(bytes_utf8)  # b'hello world'
bytes_gbk = str1.encode("gbk")  
print(bytes_gbk)  # b'hello world'
str_from_utf8 = bytes_utf8.decode("utf-8")  
print(str_from_utf8)  # hello world
str_from_gbk = bytes_gbk.decode("gbk")
print(str_from_gbk)  # hello world
# 字符串的格式化对齐
name = "Alice"
age = 30
print(f"{'Name:':<10}{name:<10}")  # Name:     Alice     
print(f"{'Age:':<10}{age:<10}")    # Age:      30        
print(f"{'Name:':>10}{name:>10}")  #      Name:     Alice
print(f"{'Age:':>10}{age:>10}")    #       Age:        30
print(f"{'Name:':^10}{name:^10}")  #   Name:    Alice   
print(f"{'Age:':^10}{age:^10}")    #    Age:      30    
# 字符串的数字格式化
number = 12345.6789
print(f"Default: {number}")               # Default: 12345.6789
print(f"Fixed-point: {number:.2f}")       # Fixed-point: 12345.68
print(f"Exponential: {number:.2e}")       # Exponential: 1.23e+04
print(f"Percentage: {number:.2%}")        # Percentage: 1234567.89%
print(f"With commas: {number:,}")         # With commas: 12,345.6789
print(f"Hexadecimal: {int(number):x}")  # Hexadecimal: 3039 
print(f"Binary: {int(number):b}")       # Binary: 11000000111001
# 字符串的多行处理
multi_line_str = """This is line one.
This is line two.This is line four."""
print(multi_line_str)       
escaped_multi_line_str = "This is line one.\nThis is line two.\nThis is line three."
print(escaped_multi_line_str)       
# 字符串的Unicode处理
unicode_str = "Hello, 世界"
print(unicode_str)  # Hello, 世界
for char in unicode_str:
    print(f"Character: {char}, Unicode code point: {ord(char)}")
# 字符串的模板格式化
from string import Template
template = Template("My name is $name and I am $age years old.")
formatted_str = template.substitute(name="Bob", age=25)
print(formatted_str)  # My name is Bob and I am 25 years old.

# 字符串的反斜杠续行
long_str = "This is a very long string that " \
           "spans multiple lines for better " \
           "readability in the code."
print(long_str)
 

# 字符串的翻转和排序
str1 = "python" 
reversed_str1 = ''.join(reversed(str1))
print(reversed_str1)  # nohtyp
sorted_str1 = ''.join(sorted(str1))
print(sorted_str1)  # hnopty

# 字符串的查找和替换高级用法
str1 = "the rain in spain stays mainly in the plain"
import re
# 查找所有以 'ain' 结尾的单词
words_ending_with_ain = re.findall(r'\b\w*ain\b', str1)
print(words_ending_with_ain)  # ['rain', 'spain', 'plain']
# 替换所有以 'ain' 结尾的单词为 'XXX'
replaced_str1 = re.sub(r'\b\w*ain\b', 'XXX', str1)
print(replaced_str1)  # the XXX in XXX stays mainly in the XXX plain    
